using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace Shrapnel
{
	public partial class View
	{
		/// <summary>
		/// The wiring dummy currently used for wiring
		/// </summary>
		private WiringDummy wiringDummy = null;

		/// <summary>
		/// The layer we are currently wiring on
		/// </summary>
		private Layer wiringLayer = null;

		/// <summary>
		/// The cable we're currently creating / wiring to an end connector
		/// </summary>
		private Cable wiringCable = null;

		/// <summary>
		/// The node we're currently creating a wire from
		/// </summary>
		private Node wiringStartNode = null;



		private bool FindFirstConnectorAtMousePosition(Point mousePosition,
			out Connector foundConnector, out Node foundNode)
		{
			// Determine which connector to start with
			PointF positionWorld = viewState.ScreenToWorld(new PointF(mousePosition.X, mousePosition.Y));
			BoundingBox selectionBox = new BoundingBox(positionWorld, new SizeF(1, 1));
			EnforceMinimumBoxSize(ref selectionBox);
			List<Element> selectedItems = GetOverlappingElements(selectionBox, false);

			foreach (Element element in selectedItems)
			{
				if ((element is Node) && (element != wiringDummy))
				{
					// Determine if the provided area contains a connector or not...
					Connector connector = ((Node)element).FindFirstOverlappingConnector(selectionBox);

					if (connector != null)
					{
						foundConnector = connector;
						foundNode = (Node)element;
						return true;
					}
				}
			}

			foundConnector = null;
			foundNode = null;
			return false;
		}

		private void OnWiringStart(Point mousePosition)
		{
			Connector startConnector;
			Node startNode;

			if (NewCableRequired != null &&
				FindFirstConnectorAtMousePosition(mousePosition, out startConnector, out startNode))
			{
				// Set up new wiring dummy
				wiringDummy = new WiringDummy();
				wiringDummy.Position = startNode.Position;
				wiringStartNode = startNode;
				wiringLayer = startNode.ParentLayer;

				// Start a new cable
				wiringCable = NewCableRequired(startConnector, wiringDummy.Connectors[0]);

				if (wiringCable != null)
				{
					wiringCable.RecalculateOccupiedArea();
					wiringLayer.Add(wiringCable);
					wiringLayer.Add(wiringDummy);
				}
			}
		}

		private void OnWiringStop(Point mousePosition)
		{
			Connector endConnector;
			Node endNode;

			// Create new cable
			if (NewCableRequired != null &&
				wiringCable != null &&
				FindFirstConnectorAtMousePosition(mousePosition, out endConnector, out endNode) &&
				(endNode.ParentLayer == wiringLayer))
			{
				Connector startConnector = wiringCable.From;
				Node startNode = wiringStartNode;

				// Is this link even allowed? Let's check both sides.
				if (startNode.AllowNewCableAtConnector(startConnector, endConnector, endNode) &&
					endNode.AllowNewCableAtConnector(endConnector, startConnector, startNode))
				{
					Cable newCable = NewCableRequired(wiringCable.From, endConnector);
					newCable.RecalculateOccupiedArea();
					wiringLayer.Add(newCable);
				}
			}

			if (wiringDummy != null)
			{
				wiringLayer.Remove(wiringDummy);
			}
			if (wiringCable != null)
			{
				wiringLayer.Remove(wiringCable);
			}
			wiringDummy = null;
			wiringLayer = null;
			wiringCable = null;
			wiringStartNode = null;

			automaticPanner.Stop();

			Invalidate();
		}

		private void OnWiringTick(Point mousePosition)
		{
			PointF positionWorld = viewState.ScreenToWorld(new PointF(mousePosition.X, mousePosition.Y));

			if (wiringDummy != null)
			{
				wiringDummy.Position = positionWorld;
				wiringCable.RecalculateOccupiedArea();

				UpdateAutomaticPanning(mousePosition);

				Invalidate();
			}
		}
	}
}
